home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / SNNSV32.ZIP / SNNSv3.2 / xgui / sources / d3_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-25  |  19.6 KB  |  687 lines

  1. /*****************************************************************************
  2.   FILE           : d3_main.c
  3.   SHORTNAME      : main.c
  4.   SNNS VERSION   : 3.2
  5.  
  6.   PURPOSE        : contains the main routine to draw the net
  7.   NOTES          :
  8.  
  9.   AUTHOR         : Ralf Huebner
  10.   DATE           : 1.12.1991
  11.  
  12.   CHANGED BY     : Niels Mache
  13.   IDENTIFICATION : @(#)d3_main.c    1.17 4/18/94
  14.   SCCS VERSION   : 1.17
  15.   LAST CHANGE    : 4/18/94
  16.  
  17.              Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG
  18.              
  19. ******************************************************************************/
  20.  
  21.  
  22. #include <math.h>
  23. #include <string.h>
  24. #include <malloc.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27.  
  28. #include "X11/Xlib.h"
  29.  
  30. #include "ui.h"
  31.  
  32. #include "glob_typ.h"    /*  Kernel constant and type definitions  */
  33. #include "d3_global.h"
  34. #include "d3_draw.h"
  35. #include "d3_anageo.h"
  36. #include "d3_graph.h"
  37. #include "d3_fonts.h"
  38. #include "d3_point.h"
  39.  
  40. #include "kr_ui.h"    /*  Kernel interface functions    */
  41.  
  42. #include "d3_zgraph.h"
  43. #include "ui_setup.h"
  44. #include "ui_color.h"
  45.  
  46. #include "d3_main.ph"
  47.  
  48.  
  49. /*****************************************************************************
  50.   FUNCTION : d3_getColorValue
  51.  
  52.   PURPOSE  : get the value of an unit for a selected mode
  53.   RETURNS  : -1.0 <= value <= 1.0
  54.   NOTES    :
  55.  
  56.   UPDATE   :
  57. ******************************************************************************/
  58.  
  59. void d3_getColorValue (int mode, int unitNo, float *value)
  60.  
  61. {
  62.     switch (mode) {
  63.          case activation_on :  *value = krui_getUnitActivation (unitNo);
  64.                                break;
  65.          case init_act_on   :  *value = krui_getUnitInitialActivation (unitNo);
  66.                                break;
  67.          case output_on     :  *value = krui_getUnitOutput (unitNo);
  68.                                break;
  69.          case bias_on       :  *value = krui_getUnitBias (unitNo);
  70.                                break;
  71.          default            :  *value = krui_getUnitActivation (unitNo);
  72.                                break;
  73.     }
  74.     if (*value > 1.0)
  75.         *value = 1.0;
  76.     if (*value < -1.0)
  77.         *value = -1.0;
  78. }
  79.  
  80.  
  81. /*****************************************************************************
  82.   FUNCTION : get_unit_pos_vector
  83.  
  84.   PURPOSE  : calculates the 3d vector form the 2d representation
  85.   RETURNS  : the vector
  86.   NOTES    : this is the only interface to get a 3d vector
  87.  
  88.   UPDATE   :
  89. ******************************************************************************/
  90.  
  91. static void get_unit_pos_vector (int unit, vector v)
  92.  
  93. {
  94.     struct PosType unit_pos;
  95.     int  x, y;
  96.  
  97.     krui_getUnitPosition (unit, &unit_pos);
  98.     krui_xyTransTable( OP_TRANSTABLE_GET, &x, &y, unit_pos.z );
  99.  
  100.     v[0]= (unit_pos.x - x) * grid_size;
  101.     v[1] = (unit_pos.y - y) * grid_size;
  102.  
  103.     v[2] = unit_pos.z * grid_size;
  104.     v[3] = 1.0;
  105. }
  106.  
  107.  
  108. /*****************************************************************************
  109.   FUNCTION : unit_transformation
  110.  
  111.   PURPOSE  : multipies a matrix with an unit cube
  112.   RETURNS  : the transformed cube
  113.   NOTES    :
  114.  
  115.   UPDATE   :
  116. ******************************************************************************/
  117.  
  118. static void unit_transformation (cube c, matrix m)
  119.  
  120. {
  121.     int i;
  122.  
  123.     for (i=0; i<ANZ_VECS; i++)
  124.       d3_multMatrixVector (c[i], m, d3_e_cube[i]);
  125. }
  126.  
  127.  
  128. /*****************************************************************************
  129.   FUNCTION : get_net_extrema
  130.  
  131.   PURPOSE  : calculates the dimensions of a net
  132.   RETURNS  : two vectors containing the minimum and the maximum of the net
  133.   NOTES    :
  134.  
  135.   UPDATE   :
  136. ******************************************************************************/
  137.  
  138. static void get_net_extrema (vector min, vector max)
  139.  
  140. {
  141.     vector p;
  142.     int act_unit, i;
  143.  
  144.     act_unit = krui_getFirstUnit ();
  145.     if (act_unit != 0)
  146.       {
  147.         get_unit_pos_vector (act_unit, min);
  148.         get_unit_pos_vector (act_unit, max);
  149.         act_unit = krui_getNextUnit ();
  150.         while (act_unit != 0)
  151.         {
  152.              get_unit_pos_vector (act_unit, p);
  153.              for (i=0; i<3; i++)
  154.                {
  155.                  if (p[i] < min[i])
  156.                    min[i] = p[i];
  157.                  if (p[i] > max[i])
  158.                    max[i] = p[i];
  159.             }
  160.              act_unit = krui_getNextUnit ();
  161.       }
  162.       }
  163.  }
  164.  
  165.  
  166. /*****************************************************************************
  167.   FUNCTION : insert_center_vector
  168.  
  169.   PURPOSE  : stores the center of a cube
  170.   RETURNS  : void
  171.   NOTES    :
  172.  
  173.   UPDATE   :
  174. ******************************************************************************/
  175.  
  176. static void insert_center_vector (cube c, int unit)
  177.  
  178. {
  179.     struct PositionVector pv;
  180.  
  181.     pv.x = c[CENTER_VECTOR][0];
  182.     pv.y = c[CENTER_VECTOR][1];
  183.     pv.z = c[CENTER_VECTOR][2];
  184.     krui_setUnitCenters (unit, d3_currentDisplay, &pv);
  185. }
  186.  
  187.  
  188. /*****************************************************************************
  189.   FUNCTION : get_size_vector
  190.  
  191.   PURPOSE  : get the value of an unit to calculate the size
  192.   RETURNS  : a vector containing the size
  193.   NOTES    : only positive values are returned
  194.  
  195.   UPDATE   :
  196. ******************************************************************************/
  197.  
  198. static bool get_size_vector (vector v, int unitNo)
  199.  
  200. {
  201.      float value;
  202.  
  203.      switch (d3_state.unit_mode.size)
  204.        {
  205.          case activation_on :  value = krui_getUnitActivation (unitNo);
  206.                                break;
  207.          case init_act_on   :  value = krui_getUnitInitialActivation(unitNo);
  208.                                break;
  209.          case output_on     :  value = krui_getUnitOutput(unitNo);
  210.                                break;
  211.          case bias_on       :  value = krui_getUnitBias(unitNo);
  212.                                break;
  213.          case nothing_on    :  value = 1.0;
  214.                                break;
  215.          default            :  value = 1.0;
  216.        }
  217.      if (value > 1.0)
  218.        value = 1.0;
  219.      v[0] = v[1] = v[2] = value;
  220.      return (value >= 0.1);
  221. }
  222.  
  223.  
  224. /*****************************************************************************
  225.   FUNCTION : get_label_string
  226.  
  227.   PURPOSE  : gets the label for an unit
  228.   RETURNS  : the string
  229.   NOTES    :
  230.  
  231.   UPDATE   :
  232. ******************************************************************************/
  233.  
  234. static char *get_label_string (int label, int unitNo)
  235.  
  236. {
  237.     char *fmt_string = "%.3f", *str;
  238.     struct PosType pos;
  239.     int len;
  240.  
  241.     str = malloc (255);
  242.     switch (label) {
  243.          case activation_on :  sprintf (str, fmt_string, 
  244.                                         krui_getUnitActivation (unitNo));
  245.                                break;
  246.          case init_act_on   :  sprintf (str, fmt_string,
  247.                                         krui_getUnitInitialActivation (unitNo));
  248.                                break;
  249.          case output_on     :  sprintf (str, fmt_string, 
  250.                                         krui_getUnitOutput (unitNo));
  251.                                break;
  252.          case bias_on       :  sprintf (str, fmt_string, 
  253.                                         krui_getUnitBias (unitNo));
  254.                                break;
  255.          case number_on     :  sprintf (str, "%d", unitNo);
  256.                                break;
  257.          case zvalue_on     :  krui_getUnitPosition (unitNo, &pos);
  258.                                sprintf (str, "%d", pos.z);
  259.                                break;
  260.          case name_on       :  sprintf (str, "%s", krui_getUnitName(unitNo));  
  261.                                if (str == NULL)
  262.                                    sprintf (str, " ");
  263.                                break;
  264.          default            :  sprintf (str, "%s", "nothing");
  265.                                break;
  266.     }
  267.     return (str);
  268. /*
  269.     len = strlen (str)+1;
  270.     if ((copy = malloc((unsigned int)len)))
  271.         bcopy(str, copy, len);  
  272. */
  273. }
  274.  
  275.  
  276. /*****************************************************************************
  277.   FUNCTION : d3_labelUnit
  278.  
  279.   PURPOSE  : draws a string at the specified vertex of a cube
  280.   RETURNS  : void
  281.   NOTES    :
  282.  
  283.   UPDATE   :
  284. ******************************************************************************/
  285.  
  286. static void d3_labelUnit (cube c, int unitNo, int vert, int label, bool toplabel_flag)
  287.  
  288. {
  289.     int x, y;
  290.     float z;
  291.     char *label_string;
  292.     
  293.     x = c[vert][0];
  294.     y = c[vert][1];
  295.     z = c[vert][2];
  296.     if (toplabel_flag)
  297.         y = y - d3_fontYsize;
  298.     label_string = get_label_string (label, unitNo);
  299.     d3_draw_string (x, y, z, label_string);     
  300. }
  301.  
  302.  
  303. /*****************************************************************************
  304.   FUNCTION : get_vert_index 
  305.  
  306.   PURPOSE  : calculates the neatest vertex for a given vector
  307.   RETURNS  : the index in the vertex structure 
  308.   NOTES    :
  309.  
  310.   UPDATE   :
  311. ******************************************************************************/
  312.  
  313. static int get_vert_index (cube c, vector corner)
  314.  
  315. {
  316.     cube vert_diff;
  317.     float length, vert_len;
  318.     int index, i, j;
  319.  
  320.     for (i=0; i<8; i++) {
  321.         for (j=0; j<3; j++) {
  322.             vert_diff[i][j] = corner[j] - c[i][j];
  323.     }
  324.     }
  325.     length = vert_diff[0][0]*vert_diff[0][0] + vert_diff[0][1]*vert_diff[0][1] +
  326.              vert_diff[0][2]*vert_diff[0][2]; 
  327.     index = 0;
  328.     for (i=1; i<8; i++) {
  329.         vert_len = vert_diff[i][0]*vert_diff[i][0] + vert_diff[i][1]*vert_diff[i][1] +
  330.                    vert_diff[i][2]*vert_diff[i][2]; 
  331.         if (vert_len < length) {
  332.              length = vert_len;
  333.              index = i;
  334.     }
  335.     }
  336.     return (index);         
  337. }
  338.  
  339.  
  340. /*****************************************************************************
  341.   FUNCTION : get_label_vert_indices
  342.  
  343.   PURPOSE  : gets the vertex indices of the upper right and the lower right
  344.              vertex for a given rotation
  345.   RETURNS  : the two indices
  346.   NOTES    :
  347.  
  348.   UPDATE   :
  349. ******************************************************************************/
  350.  
  351. static void get_label_vert_indices (vector rot_vec, int *top_index, int *bott_index)
  352.  
  353. {
  354.     static vector upper_corner = {0.0, -0.5, -0.5, 1.0};
  355.     static vector lower_corner = {0.0, 0.5, -0.5, 1.0};
  356.     cube c;
  357.  
  358.     d3_rotateCube (c, rot_vec, d3_e_cube);
  359.     *top_index = get_vert_index (c, upper_corner);
  360.     *bott_index = get_vert_index (c, lower_corner);
  361. }
  362.  
  363.  
  364. /*****************************************************************************
  365.   FUNCTION : calc_transformed_cube
  366.  
  367.   PURPOSE  : multplies all matices for the viewing pipeline
  368.   RETURNS  : the transformed cube
  369.   NOTES    :
  370.  
  371.   UPDATE   :
  372. ******************************************************************************/
  373.  
  374. static void calc_transformed_cube (matrix unit_trans_mat, matrix world_center_mat,
  375.                                    matrix unit_scale_mat, matrix unit_activ_mat,
  376.                                    matrix world_scale_mat, matrix world_trans_mat, 
  377.                                    vector viewpoint, cube transformed_cube)
  378.  
  379. {
  380.     matrix trans_mat, scale_mat, unit_mat, world_mat, global_mat;
  381.     cube c1, c2;
  382.  
  383.     d3_multMatrix (trans_mat, world_center_mat, unit_trans_mat);
  384.     d3_multMatrix (scale_mat, unit_activ_mat, unit_scale_mat);
  385.     d3_multMatrix (unit_mat, trans_mat, scale_mat);
  386.     d3_multMatrix (world_mat, world_trans_mat, world_scale_mat);
  387.     d3_multMatrix (global_mat, world_mat, unit_mat);
  388.  
  389.     unit_transformation (c1, global_mat);
  390.  
  391.     d3_rotateCube (c2, d3_state.rot_vec, c1);
  392.  
  393.     d3_shiftCube (transformed_cube, c2, trans_x, trans_y);
  394.     if (d3_state.projection_mode == central)
  395.        d3_projection (transformed_cube, viewpoint, transformed_cube);
  396. }
  397.  
  398.  
  399. /*****************************************************************************
  400.   FUNCTION : draw_units
  401.  
  402.   PURPOSE  : draw all units of the net
  403.   RETURNS  : void
  404.   NOTES    : the centers of the the units are stored
  405.  
  406.   UPDATE   :
  407. ******************************************************************************/
  408.  
  409. static void draw_units (void)
  410.  
  411. {
  412.     cube transformed_cube;
  413.     vector min, max, center, p, unit_scale, activ_vec, vp, lp;
  414.     matrix world_center_mat, world_scale_mat, world_trans_mat;
  415.     matrix unit_scale_mat, unit_trans_mat, unit_activ_mat;
  416.     int act_unit, i, top_vert_index, bott_vert_index, do_draw;
  417.  
  418.     d3_shiftVector (vp, d3_state.viewpoint, trans_x, trans_y);
  419.     d3_shiftVector (lp, d3_state.light.position, trans_x, trans_y);
  420.  
  421.     get_net_extrema (min, max);
  422.     for (i=0; i<3; i++)
  423.       center[i] = -(max[i] - min[i]) / 2.0 - min[i];
  424.     center[3] = 1.0;
  425.     d3_transMatrix (world_center_mat, center);
  426.     unit_scale[0] = unit_scale[1] = unit_scale[2] = grid_size * 
  427.            d3_state.unit_aspect;
  428.     d3_scaleMatrix (unit_scale_mat, unit_scale);
  429.     d3_scaleMatrix (world_scale_mat, d3_state.scale_vec);
  430.     d3_transMatrix (world_trans_mat, d3_state.trans_vec);
  431.  
  432.     get_label_vert_indices (d3_state.rot_vec, &top_vert_index, &bott_vert_index);   
  433.  
  434.     act_unit = krui_getFirstUnit ();
  435.     while (act_unit != 0) {
  436.          get_unit_pos_vector (act_unit, p);
  437.          d3_transMatrix (unit_trans_mat, p);
  438.          do_draw = get_size_vector (activ_vec, act_unit);
  439.          d3_scaleMatrix (unit_activ_mat, activ_vec);
  440.          calc_transformed_cube (unit_trans_mat, world_center_mat, 
  441.                                 unit_scale_mat,
  442.                                 unit_activ_mat, world_scale_mat,
  443.                                 world_trans_mat, vp, transformed_cube);
  444.          insert_center_vector (transformed_cube, act_unit);
  445.          if (do_draw) {
  446.               if (d3_state.model_mode == wire_frame)
  447.                   d3_draw_wireframeCube (transformed_cube);
  448.               else {
  449.                   
  450.                   d3_draw_solidCube (transformed_cube, vp, lp, act_unit);
  451.           }
  452.               if (d3_state.unit_mode.top_label != nothing_on)
  453.                   d3_labelUnit (transformed_cube, act_unit, top_vert_index, 
  454.                                 d3_state.unit_mode.top_label, TRUE);
  455.               if (d3_state.unit_mode.bottom_label != nothing_on)
  456.                   d3_labelUnit (transformed_cube, act_unit, bott_vert_index, 
  457.                                d3_state.unit_mode.bottom_label, FALSE);
  458.      }
  459.          act_unit = krui_getNextUnit ();
  460.     }
  461. }
  462.  
  463.  
  464. /*****************************************************************************
  465.   FUNCTION : d3_labelLink
  466.  
  467.   PURPOSE  : draws the weight of a link 
  468.   RETURNS  : void
  469.   NOTES    :
  470.  
  471.   UPDATE   :
  472. ******************************************************************************/
  473.  
  474. static void d3_labelLink (vector v1, vector v2, float *weight)
  475.  
  476. {
  477.     char string[40];
  478.     int dx, dy;
  479.     float dz;
  480.  
  481.     dx = floor (v1[0] + (v2[0] - v1[0]) / 2);
  482.     dy = floor (v1[1] + (v2[1] - v1[1]) / 2);
  483.     dz = v1[2] + (v2[2] - v1[2]) / 2;
  484.     sprintf (string, "%.3f", *weight);
  485.     d3_setBlackColor ();
  486.     d3_draw_string (dx, dy, dz, string);      
  487.     d3_setColor (linkColor);
  488. }
  489.  
  490.  
  491. /*****************************************************************************
  492.   FUNCTION : draw_links
  493.  
  494.   PURPOSE  : draws all links of the net
  495.   RETURNS  : void
  496.   NOTES    :
  497.  
  498.   UPDATE   : 8.3.93  Link Trigger
  499. ******************************************************************************/
  500.  
  501. static void draw_links (void)
  502.  
  503. {
  504.     int act_unit, pred_unit;
  505.     FlintType str;    /* old style: FlintType *str */
  506.     struct PositionVector *start_vec, *end_vec;
  507.     vector v1, v2;
  508.  
  509.     if (d3_state.model_mode == solid) {
  510.          d3_setColor (linkColor);
  511.          if (d3_state.color_mode == mono_mode) {
  512.               d3_setBlackColor ();    
  513.               d3_intens = 0.0;
  514.      }
  515.     } else {
  516.          d3_setBlackColor ();    
  517.          d3_intens = 0.0;
  518.     }
  519.  
  520.     act_unit = krui_getFirstUnit ();
  521.     while (act_unit != 0) {
  522.          pred_unit = krui_getFirstPredUnit (&str); 
  523.          while (pred_unit != 0) {
  524.               krui_getUnitCenters (act_unit, d3_currentDisplay, &start_vec);
  525.               krui_getUnitCenters (pred_unit, d3_currentDisplay, &end_vec);
  526.               v1[0] = start_vec->x;
  527.               v1[1] = start_vec->y;
  528.               v1[2] = start_vec->z;
  529.               v2[0] = end_vec->x;
  530.               v2[1] = end_vec->y;
  531.               v2[2] = end_vec->z;
  532.  
  533.               if ((str >= d3_state.pos_link_trigger) 
  534.                    OR (str <= -d3_state.neg_link_trigger)) { 
  535.                   if (d3_state.model_mode == wire_frame)
  536.                       d3_draw_wireframeLine (v1, v2);
  537.                   else {
  538.                       if ((d3_state.link_mode == links_color) && 
  539.                           (d3_state.color_mode == rgb_mode))
  540.                           d3_setLinkColor (&str);
  541.                       if (d3_state.color_mode == mono_mode)
  542.                           d3_setBlackColor (); 
  543.                       d3_draw_solidLine (v1, v2);
  544.               }
  545.                   if (d3_state.link_mode == links_label)
  546.                       d3_labelLink (v1, v2, &str);
  547.           }
  548.               pred_unit = krui_getNextPredUnit (&str);
  549.          }
  550.          act_unit = krui_getNextUnit ();
  551.     }
  552.     if (d3_state.model_mode == solid)
  553.         d3_flushPixels ();
  554. }
  555.  
  556.  
  557. /*****************************************************************************
  558.   FUNCTION : d3_drawNet
  559.  
  560.   PURPOSE  : draws the whole net
  561.   RETURNS  : void
  562.   NOTES    : this routine is called by every redraw request
  563.  
  564.   UPDATE   :
  565. ******************************************************************************/
  566.  
  567. void d3_drawNet (void)
  568.  
  569. {
  570.     if (d3_freeze)
  571.         return;
  572.     if (d3_displayIsReady) {
  573.         if (d3_state.model_mode == solid)
  574.             d3_clearZbuffer ();
  575.         else
  576.             d3_setBlackColor ();
  577.         d3_clearDisplay ();   /* old style: d3_clearDispaly */
  578.         draw_units ();
  579.         if (d3_state.link_mode != links_off)
  580.             draw_links ();
  581.     }
  582.  
  583. }
  584.  
  585.  
  586. /*****************************************************************************
  587.   FUNCTION : d3_recenter_window
  588.  
  589.   PURPOSE  : calculate the new dimensions if the window is resized by the user 
  590.   RETURNS  : new dimension values
  591.   NOTES    : called by the X-Event Handler  
  592.  
  593.   UPDATE   :
  594. ******************************************************************************/
  595.  
  596. void d3_recenter_window (int width, int height)
  597.  
  598. {
  599.    if ((width != d3_displayXsize) || (height != d3_displayYsize)) {
  600.       d3_displayXsize = width;
  601.       d3_displayYsize = height;
  602.       trans_x = width / 2;
  603.       trans_y = height / 2;
  604.       d3_setClipWindow (0, 0, d3_displayXsize, d3_displayYsize);
  605.    }
  606. }
  607.  
  608.  
  609. /*****************************************************************************
  610.   FUNCTION : d3_resetDisplay
  611.  
  612.   PURPOSE  : set all translations, scalings and rotations to zero
  613.   RETURNS  : void
  614.   NOTES    :
  615.  
  616.   UPDATE   :
  617. ******************************************************************************/
  618.  
  619. void d3_resetDisplay (void)
  620.  
  621. {
  622.     int i;
  623.  
  624.     if (d3_freeze)
  625.         return;
  626.     for (i=0; i<3; i++)
  627.       {
  628.          d3_state.scale_vec [i] = 1.0; 
  629.          d3_state.trans_vec [i] = 0.0; 
  630.          d3_state.rot_vec [i] = 0.0; 
  631.       }
  632.     d3_drawNet ();
  633. }
  634.  
  635.  
  636. /*****************************************************************************
  637.   FUNCTION : d3_clear_xyTranslationTable
  638.  
  639.   PURPOSE  : clears the Translation Table for the 2d -> 3d mapping
  640.   RETURNS  : the cleared Table
  641.   NOTES    :
  642.  
  643.   UPDATE   :
  644. ******************************************************************************/
  645.  
  646. void d3_clear_xyTranslationTable (void)
  647.  
  648. {
  649.     int i;
  650.  
  651.     krui_xyTransTable( OP_TRANSTABLE_CLEAR, NULL, NULL, 0 );
  652. }
  653.  
  654.  
  655. /*****************************************************************************
  656.   FUNCTION : d3_init_main
  657.  
  658.   PURPOSE  : this is the initialization for the Translation Table, the Fonts,
  659.              the color, and the dimensions
  660.   RETURNS  : void
  661.   NOTES    : only called one time by ui_init
  662.  
  663.   UPDATE   :
  664. ******************************************************************************/
  665.  
  666. void d3_init_main (void)
  667.  
  668. {
  669.     trans_x = d3_displayXsize / 2.0;
  670.     trans_y = d3_displayYsize / 2.0;
  671.  
  672.     d3_setClipWindow (0, 0, d3_displayXsize, d3_displayYsize);
  673.  
  674.     if (ui_col_monochromeMode)
  675.         d3_state.color_mode = mono_mode;
  676.     else
  677.         d3_state.color_mode = rgb_mode;
  678.     
  679.     d3_select_font (fnt8x14);
  680.     d3_get_font_size (&d3_fontXsize, &d3_fontYsize);
  681. }
  682.  
  683.  
  684.  
  685. /* end of file */
  686. /* lines: 817 */
  687.